

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>

#include "uart.h"

#define UART_RECV_BUFF_SIZE 1024
static void *uart_read_thread(void *args)
{
    UART_T *tmp = (UART_T *)args;

#if 0
    fd_set rset;
    char recv_buff[UART_RECV_BUFF_SIZE];
    int ready;
    int rsize;
    while (1)
    {
    
        FD_ZERO(&rset);
        FD_SET(tmp->uart_fd, &rset);

        ready = select(tmp->uart_fd + 1, &rset, NULL, NULL, NULL);

        if (ready == -1)
        {
            if (errno == EINTR)
            {
                continue;
            }

            return NULL;
        }

        if (ready == 0)
        {
            continue;
        }

        if (FD_ISSET(tmp->uart_fd, &rset))
        {
            memset(recv_buff, 0, UART_RECV_BUFF_SIZE);
            if ((rsize = read(tmp->uart_fd, recv_buff, UART_RECV_BUFF_SIZE)) > 0)
            {
                tmp->func_call_read(recv_buff, rsize);
            }
        }
    }
#endif

    int count = 0;
    char recv_buff[UART_RECV_BUFF_SIZE];
    char c;
    while (1)
    {
        memset(recv_buff, 0, UART_RECV_BUFF_SIZE);
        char *tmp_str = recv_buff;
        while (read(tmp->uart_fd, &c, 1) > 0)
        {
            *tmp_str = c;
            tmp_str++;

            count++;

            if (c == '\n')
            {
                break;
            }
        }

        printf("\n\n%s %d count=%d\n\n", __FILE__, __LINE__, count);

        if (count == 50 && recv_buff[count - 2] == '\r')
        {
            tmp->func_call_read(recv_buff, count);
        }

        count = 0;
    }

    return NULL;
}

int uart_open(char *com_port, UART_T *uart_t)
{
    int tty_fd = open(com_port, O_RDWR | O_NOCTTY);
    if (tty_fd == -1)
    {
        return -1;
    }

    uart_t->uart_fd = tty_fd;
    uart_t->func_call_read = NULL;

    return 0;
}

void uart_set(int nSpeed, int nBits, char nEvent, int nStop, UART_T *uart_t)
{

    struct termios newtio, oldtio;
    if (tcgetattr(uart_t->uart_fd, &oldtio) != 0)
    {
        perror("SetupSerial 1");
        return;
    }
    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    switch (nBits)
    {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch (nEvent)
    {
    case 'O': //奇校验
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E': //偶校验
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N': //无校验
        newtio.c_cflag &= ~PARENB;
        break;
    }

    switch (nSpeed)
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    if (nStop == 1)
    {
        newtio.c_cflag &= ~CSTOPB;
    }
    else if (nStop == 2)
    {
        newtio.c_cflag |= CSTOPB;
    }
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 50;
    tcflush(uart_t->uart_fd, TCIFLUSH);
    if ((tcsetattr(uart_t->uart_fd, TCSANOW, &newtio)) != 0)
    {
        perror("com set error");
        return;
    }
    //  printf("set done!\n");
    return;
}

void uart_read_register(read_func_ptr read_call, UART_T *uart_t)
{
    assert(read_call != NULL);

    uart_t->func_call_read = read_call;
}

void uart_read_event_start(UART_T *uart_t)
{

    pthread_t tid;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_create(&tid, &attr, uart_read_thread, (void *)uart_t);
}

int uart_send(UART_T *uart_t, char *data, int len)
{
    return write(uart_t->uart_fd, data, len);
}